import { ElMessageBox } from "element-plus";
import { Time } from "./time";
import { cloneDeep } from "lodash";

class Utils {
    title: string
    show: boolean
    loading: boolean
    hasChanged: boolean
    proxyValue: ProxyHandler<Object>
    errkey?: string
    VALEXP: { [key: string]: RegExp; };
    constructor() {
        this.title = ""
        this.show = false
        this.loading = false
        this.hasChanged = false
        this.VALEXP = { PHONE: /^1\d{10}$/ }
        this.proxyValue = {
            get: (target, key) => {
                if (typeof key === "symbol") return true
                let d: any = target
                try {
                    key.split('.').forEach(item => {
                        if (d)
                            d = d[item]
                        else
                            throw new Error('not find')
                    })
                } catch (err: any) {
                    if (err.message === "not find") {
                        return undefined
                    }
                }
                return d
            },
            set: (target, key, value) => {
                if (typeof key === "symbol") return true
                let d: any = target
                const keys = key.split('.')
                const last = keys.pop() || key
                keys.forEach(item => {
                    d[item] ? null : d[item] = {}
                    d = d[item]
                })
                d[last] = value
                return true
            }
        }
    }
    static timer: any = undefined
    static utils_debounce(func: Function, delay: number = 500, ...arg: any[]) {
        if (this.timer) {
            clearTimeout(this.timer)
        }
        this.timer = setTimeout(() => {
            func(...arg)
        }, delay)
    }
    utils_getdate(date: string | number = new Date().toLocaleString()): Time {
        return new Time(date)
    }
    utils_setitem(target: any, en: any, keys?: string[]) {
        if (keys) {
            keys.forEach(item => {
                target[item] = en[item]
            })
        } else {
            Object.keys(target).forEach((key: string) => {
                if (en[key] !== undefined) {
                    target[key] = en[key]
                }
            })
        }
    }
    utils_confirm() {
        if (!localStorage.getItem('unConfirm')) {
            return new Promise((res) => {
                res(true)
            })
        } else {
            return ElMessageBox.confirm(
                '关闭将不保留数据，是否确认',
                {
                    confirmButtonText: '确认',
                    cancelButtonText: '取消',
                    type: 'warning',
                }
            )
        }
    }
    utils_clone(data: any) {
        return cloneDeep(data)
    }
    utils_deep_search(target: any[], config: { label: string, children: string }, key?: any, cb?: any) {
        //返回label与key相同的项
        const { label, children } = config
        let r: any = {};
        const fun = (tar: any[]) => {
            tar.forEach(item => {
                if (item[label] === key) {
                    r = item
                }
                cb && cb(item)
                item[children] && fun(item[children])
            })
        }
        fun(target)
        return r
    }
    utils_proxy_set<T extends object>(target: T, cb: (target: T, key: PropertyKey, value: any, recerver: T) => any): T {
        return new Proxy(target, {
            set: (target, key, value, recerver) => {
                const v = cb(target, key, value, recerver)
                const val = v !== undefined ? v : value
                return Reflect.set(target, key, val, recerver)
            }
        })
    }
    utils_hasChanged(porxyary?: string[]) {
        return new Proxy(this, {
            set: (target, key: string, value, recerver) => {
                if (porxyary) {
                    if (porxyary.includes(key)) {
                        if (target.hasChanged === false) {
                            recerver.hasChanged = true
                        }
                    }
                } else {
                    if (key !== "hasChanged") {
                        if (target.hasChanged === false) {
                            recerver.hasChanged = true
                        }
                    }
                }
                return Reflect.set(target, key, value, recerver)
            }
        })
    }
    utils_param(obj: any) {
        if (!obj) return ''
        const s: string[] = [];
        Object.keys(obj).forEach(key => {
            let value = obj[key]
            if (value instanceof Object) {
                value = JSON.stringify(value)
            }
            s.push(key + '=' + value + '&');
        });
        const n = '?' + s.join('');
        return n.replace(/&$/, '');
    }
    static trc(target: any, { key, child }: { key: string, child: string } = { key: 'key', child: 'child' }): Map<string, any> {
        const fun = (children: any[], parents?: { [key: string]: any }): any => {
            const m: Map<string, any> = new Map()
            children.forEach(item => {
                item.parents = parents
                m.set(item[key], item)
                item[child] = item[child] && fun(item[child], item)
            })
            return m
        }
        return fun(target)
    }
    static trcForeach(target: Map<string, any>, cb: any, { child }: { key: string, child: string } = { key: 'key', child: 'child' }) {
        const fun = (children: Map<string, any>) => {
            const deletes: string[] = []
            children.forEach((value, key) => {
                deletes.push(cb(key, value))
                value[child] && fun(value[child])
            })
            deletes.forEach(item => {
                children.delete(item)
            })
        }
        fun(target)
    }
}

export {
    Utils
}